#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
BizyAIR API调用功能
支持多种类型的图像生成和处理任务
"""

import gradio as gr
import requests
import json
import os
import base64
import threading
from datetime import datetime
from PIL import Image
import io
from typing import Dict, List, Any, Optional, Tuple

class BizyAIRManager:
    """BizyAIR API管理器"""
    
    def __init__(self):
        self.api_url = "https://api.bizyair.cn/w/v1/webapp/task/openapi/create"
        self.api_key_file = "BIZYAIR_API_KEY.env"
        self.api_keys = []
        self.current_key_index = 0
        self.lock = threading.Lock()
        self.load_api_keys()
        
        # 创建必要的目录
        self.ensure_directories()
    
    def ensure_directories(self):
        """确保必要的目录存在"""
        os.makedirs("temp", exist_ok=True)
        os.makedirs("downloads", exist_ok=True)
        
        # 创建日期子目录
        today = datetime.now().strftime("%Y%m%d")
        os.makedirs(f"temp/{today}", exist_ok=True)
    
    def load_api_keys(self):
        """加载API密钥"""
        # 从环境变量加载
        env_key = os.getenv("BIZYAIR_API_KEY")
        if env_key and env_key.strip():
            self.api_keys.append(env_key.strip())
        
        # 从文件加载
        if os.path.exists(self.api_key_file):
            try:
                with open(self.api_key_file, 'r', encoding='utf-8') as f:
                    file_keys = [line.strip() for line in f.readlines() if line.strip()]
                    self.api_keys.extend(file_keys)
            except Exception as e:
                print(f"加载API密钥文件时出错: {e}")
        
        # 去重并保持顺序
        seen = set()
        unique_keys = []
        for key in self.api_keys:
            if key not in seen:
                seen.add(key)
                unique_keys.append(key)
        self.api_keys = unique_keys
    
    def save_api_key(self, api_key: str) -> str:
        """保存API密钥到文件"""
        if not api_key or not api_key.strip():
            return "API密钥不能为空"
        
        api_key = api_key.strip()
        
        # 检查是否已存在
        if api_key in self.api_keys:
            return f"API密钥已存在，当前共有 {len(self.api_keys)} 个密钥"
        
        # 添加到列表
        self.api_keys.insert(0, api_key)  # 新密钥优先
        
        # 保存到文件
        try:
            with open(self.api_key_file, 'w', encoding='utf-8') as f:
                for key in self.api_keys:
                    f.write(f"{key}\n")
            return f"API密钥已保存，当前共有 {len(self.api_keys)} 个密钥"
        except Exception as e:
            return f"保存API密钥时出错: {e}"
    
    def get_current_api_key(self, custom_key: str = "") -> str:
        """获取当前使用的API密钥"""
        # 优先使用自定义输入的密钥
        if custom_key and custom_key.strip():
            # 保存自定义密钥
            self.save_api_key(custom_key.strip())
            return custom_key.strip()
        
        # 使用已保存的密钥（轮换）
        if self.api_keys:
            with self.lock:
                current_key = self.api_keys[self.current_key_index]
                self.current_key_index = (self.current_key_index + 1) % len(self.api_keys)
                return current_key
        
        return ""
    
    def image_to_webp_base64(self, image_path: str) -> Tuple[str, str]:
        """将图片转换为WebP格式的base64编码"""
        try:
            # 打开图片
            with Image.open(image_path) as img:
                # 转换为RGB（如果是RGBA或其他格式）
                if img.mode in ('RGBA', 'LA', 'P'):
                    background = Image.new('RGB', img.size, (255, 255, 255))
                    if img.mode == 'P':
                        img = img.convert('RGBA')
                    background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
                    img = background
                elif img.mode != 'RGB':
                    img = img.convert('RGB')
                
                # 保存为WebP格式到临时文件
                today = datetime.now().strftime("%Y%m%d")
                timestamp = datetime.now().strftime("%H%M%S")
                temp_path = f"temp/{today}/img_{timestamp}.webp"
                
                # 保存WebP文件
                img.save(temp_path, 'WEBP', quality=90)
                
                # 转换为base64
                with io.BytesIO() as buffer:
                    img.save(buffer, format='WEBP', quality=90)
                    img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
                
                return f"data:image/webp;base64,{img_base64}", temp_path
                
        except Exception as e:
            raise Exception(f"图片处理失败: {e}")
    
    def download_image(self, url: str, filename: str) -> str:
        """下载图片到downloads目录"""
        try:
            response = requests.get(url, timeout=30)
            response.raise_for_status()
            
            filepath = f"downloads/{filename}"
            with open(filepath, 'wb') as f:
                f.write(response.content)
            
            return filepath
        except Exception as e:
            raise Exception(f"下载图片失败: {e}")
    
    def save_log(self, filename: str, data: Dict, uploaded_images: List[str], 
                 request_id: str, outputs: List[Dict]) -> str:
        """保存日志文件"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "request_data": data,
            "uploaded_images": uploaded_images,
            "request_id": request_id,
            "outputs": outputs
        }
        
        log_file = f"downloads/{filename}.log"
        try:
            with open(log_file, 'w', encoding='utf-8') as f:
                json.dump(log_data, f, ensure_ascii=False, indent=2)
            return log_file
        except Exception as e:
            return f"保存日志失败: {e}"

# 全局管理器实例
bizy_manager = BizyAIRManager()



def create_input_fields():
    """创建动态输入字段"""
    fields = {}
    
    # 第一行：文本提示词独占一行
    with gr.Row():
        with gr.Column():
            fields['text_prompt'] = gr.Textbox(
                label="文本提示词",
                lines=4,
                placeholder="输入图像生成或修改的描述...",
                visible=True
            )
            fields['text_prompt_field'] = gr.Textbox(
                label="文本提示词字段映射",
                placeholder="如: 14:PrimitiveStringMultiline.value",
                value="14:PrimitiveStringMultiline.value",
                visible=True
            )
    
    # 第二行：图片1独占一行
    with gr.Row():
        with gr.Column():
            fields['image_1'] = gr.Image(
                label="图片 1",
                type="filepath",
                visible=True
            )
            with gr.Row():
                fields['image_url_1'] = gr.Textbox(
                    label="图片 1 URL (可选)",
                    placeholder="输入图片URL地址",
                    visible=True,
                    scale=2
                )
                fields['image_1_field'] = gr.Textbox(
                    label="图片 1 字段映射",
                    placeholder="如: 2:LoadImage.image",
                    value="2:LoadImage.image",
                    visible=True,
                    scale=1
                )
    
    # 第三行：图片2和图片3分两列
    with gr.Row():
        with gr.Column():
            fields['image_2'] = gr.Image(
                label="图片 2",
                type="filepath",
                visible=True
            )
            with gr.Row():
                fields['image_url_2'] = gr.Textbox(
                    label="图片 2 URL (可选)",
                    placeholder="输入图片URL地址",
                    visible=True,
                    scale=2
                )
                fields['image_2_field'] = gr.Textbox(
                    label="图片 2 字段映射",
                    placeholder="如: 18:LoadImage.image",
                    value="18:LoadImage.image",
                    visible=True,
                    scale=1
                )
        with gr.Column():
            fields['image_3'] = gr.Image(
                label="图片 3",
                type="filepath",
                visible=True
            )
            with gr.Row():
                fields['image_url_3'] = gr.Textbox(
                    label="图片 3 URL (可选)",
                    placeholder="输入图片URL地址",
                    visible=True,
                    scale=2
                )
                fields['image_3_field'] = gr.Textbox(
                    label="图片 3 字段映射",
                    placeholder="如: 19:LoadImage.image",
                    value="19:LoadImage.image",
                    visible=True,
                    scale=1
                )
    
    # 第四行：图片4和图片5分两列
    with gr.Row():
        with gr.Column():
            fields['image_4'] = gr.Image(
                label="图片 4",
                type="filepath",
                visible=True
            )
            with gr.Row():
                fields['image_url_4'] = gr.Textbox(
                    label="图片 4 URL (可选)",
                    placeholder="输入图片URL地址",
                    visible=True,
                    scale=2
                )
                fields['image_4_field'] = gr.Textbox(
                    label="图片 4 字段映射",
                    placeholder="如: 20:LoadImage.image",
                    value="20:LoadImage.image",
                    visible=True,
                    scale=1
                )
        with gr.Column():
            fields['image_5'] = gr.Image(
                label="图片 5",
                type="filepath",
                visible=True
            )
            with gr.Row():
                fields['image_url_5'] = gr.Textbox(
                    label="图片 5 URL (可选)",
                    placeholder="输入图片URL地址",
                    visible=True,
                    scale=2
                )
                fields['image_5_field'] = gr.Textbox(
                    label="图片 5 字段映射",
                    placeholder="如: 21:LoadImage.image",
                    value="21:LoadImage.image",
                    visible=True,
                    scale=1
                )
    
    # 数值参数区域
    with gr.Row():
        with gr.Column():
            fields['float_value'] = gr.Slider(
                label="放大倍数（1-4倍）",
                minimum=1,
                maximum=4,
                step=1,
                value=2,
                visible=False
            )
            fields['float_field'] = gr.Textbox(
                label="放大倍数字段映射",
                placeholder="如: 99:easy float.value",
                value="99:easy float.value",
                visible=False
            )
        with gr.Column():
            fields['int_value'] = gr.Number(
                label="整数参数",
                value=88888,
                precision=0,
                visible=False
            )
            fields['int_field'] = gr.Textbox(
                label="整数参数字段映射",
                placeholder="如: custom:int.value",
                value="custom:int.value",
                visible=False
            )
    
    return fields

def update_input_visibility(input_type):
    """根据选择的功能类型更新输入字段的可见性、web_app_id和字段映射"""
    # 定义每种类型的配置信息
    type_config = {
        "单图修改": {
            "images": 1, "text": True, "float": False, "int": False, "web_app_id": 36256,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["2:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "单图放大": {
            "images": 1, "text": False, "float": True, "int": False, "web_app_id": 36258,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["98:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "单图重绘": {
            "images": 1, "text": False, "float": False, "int": False, "web_app_id": 36259,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["91:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "双图融合": {
            "images": 2, "text": True, "float": False, "int": False, "web_app_id": 34887,
            "text_field": "77:PrimitiveStringMultiline.value",
            "image_fields": ["74:LoadImage.image", "75:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "三图融合": {
            "images": 3, "text": True, "float": False, "int": False, "web_app_id": 36277,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["2:LoadImage.image", "18:LoadImage.image", "19:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "四图融合": {
            "images": 4, "text": True, "float": False, "int": False, "web_app_id": 36278,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["2:LoadImage.image", "18:LoadImage.image", "19:LoadImage.image", "20:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
        "五图融合": {
            "images": 5, "text": True, "float": False, "int": False, "web_app_id": 36271,
            "text_field": "14:PrimitiveStringMultiline.value",
            "image_fields": ["2:LoadImage.image", "18:LoadImage.image", "19:LoadImage.image", "20:LoadImage.image", "21:LoadImage.image"],
            "float_field": "99:easy float.value"
        },
    }
    
    config = type_config.get(input_type, type_config["五图融合"])
    image_count = config["images"]
    
    # 生成图片状态和字段映射
    image_states = []
    for i in range(5):
        if i < image_count:
            # 激活状态 - 使用对应的字段映射
            field_value = config["image_fields"][i] if i < len(config["image_fields"]) else ""
            image_states.append({
                "image_visible": True, "image_interactive": True,
                "url_visible": True, "url_interactive": True,
                "field_visible": True, "field_interactive": True,
                "image_label": f"图片 {i+1} (必需)",
                "url_label": f"图片 {i+1} URL (可选)",
                "field_label": f"图片 {i+1} 字段映射",
                "field_value": field_value
            })
        else:
            # 未激活状态 - 清空字段映射
            image_states.append({
                "image_visible": True, "image_interactive": False,
                "url_visible": True, "url_interactive": False,
                "field_visible": True, "field_interactive": False,
                "image_label": f"图片 {i+1} (未使用)",
                "url_label": f"图片 {i+1} URL (未使用)",
                "field_label": f"图片 {i+1} 字段映射 (未使用)",
                "field_value": ""  # 清空多余的字段映射
            })
    
    # 返回更新状态（按照输出顺序）
    return [
        gr.update(value=config["web_app_id"]),  # web_app_id
        
        # 文本提示词
        gr.update(visible=config["text"]),
        gr.update(value=config["text_field"], visible=config["text"]),
        
        # 图片1
        gr.update(visible=image_states[0]["image_visible"], interactive=image_states[0]["image_interactive"], label=image_states[0]["image_label"]),
        gr.update(visible=image_states[0]["url_visible"], interactive=image_states[0]["url_interactive"], label=image_states[0]["url_label"]),
        gr.update(value=image_states[0]["field_value"], visible=image_states[0]["field_visible"], interactive=image_states[0]["field_interactive"], label=image_states[0]["field_label"]),
        
        # 图片2
        gr.update(visible=image_states[1]["image_visible"], interactive=image_states[1]["image_interactive"], label=image_states[1]["image_label"]),
        gr.update(visible=image_states[1]["url_visible"], interactive=image_states[1]["url_interactive"], label=image_states[1]["url_label"]),
        gr.update(value=image_states[1]["field_value"], visible=image_states[1]["field_visible"], interactive=image_states[1]["field_interactive"], label=image_states[1]["field_label"]),
        
        # 图片3
        gr.update(visible=image_states[2]["image_visible"], interactive=image_states[2]["image_interactive"], label=image_states[2]["image_label"]),
        gr.update(visible=image_states[2]["url_visible"], interactive=image_states[2]["url_interactive"], label=image_states[2]["url_label"]),
        gr.update(value=image_states[2]["field_value"], visible=image_states[2]["field_visible"], interactive=image_states[2]["field_interactive"], label=image_states[2]["field_label"]),
        
        # 图片4
        gr.update(visible=image_states[3]["image_visible"], interactive=image_states[3]["image_interactive"], label=image_states[3]["image_label"]),
        gr.update(visible=image_states[3]["url_visible"], interactive=image_states[3]["url_interactive"], label=image_states[3]["url_label"]),
        gr.update(value=image_states[3]["field_value"], visible=image_states[3]["field_visible"], interactive=image_states[3]["field_interactive"], label=image_states[3]["field_label"]),
        
        # 图片5
        gr.update(visible=image_states[4]["image_visible"], interactive=image_states[4]["image_interactive"], label=image_states[4]["image_label"]),
        gr.update(visible=image_states[4]["url_visible"], interactive=image_states[4]["url_interactive"], label=image_states[4]["url_label"]),
        gr.update(value=image_states[4]["field_value"], visible=image_states[4]["field_visible"], interactive=image_states[4]["field_interactive"], label=image_states[4]["field_label"]),
        
        # 数值参数
        gr.update(visible=config["float"]),  # float_value
        gr.update(value=config["float_field"], visible=config["float"]),  # float_field
        gr.update(visible=config["int"]),  # int_value
        gr.update(visible=config["int"])  # int_field
    ]

def process_api_request(api_key, web_app_id, input_type, 
                       text_prompt, text_prompt_field, 
                       image_1, image_url_1, image_1_field,
                       image_2, image_url_2, image_2_field,
                       image_3, image_url_3, image_3_field,
                       image_4, image_url_4, image_4_field,
                       image_5, image_url_5, image_5_field,
                       float_value, float_field, int_value, int_field):
    """处理API请求，使用自定义字段映射"""
    try:
        # 调试信息：显示所有接收到的参数
        print(f"\n=== 参数调试信息 ===\n功能类型: {input_type}")
        print(f"文本提示词: {text_prompt}")
        print(f"文本字段映射: {text_prompt_field}")
        for i in range(1, 6):
            image_file = locals()[f'image_{i}']
            image_url = locals()[f'image_url_{i}']
            image_field = locals()[f'image_{i}_field']
            print(f"image_{i}: {image_file}")
            print(f"image_url_{i}: {image_url}")
            print(f"image_{i}_field: {image_field}")
        print(f"float_value: {float_value}, float_field: {float_field}")
        print(f"int_value: {int_value}, int_field: {int_field}")
        print("=== 参数调试结束 ===")
        
        # 获取API密钥
        current_api_key = bizy_manager.get_current_api_key(api_key)
        if not current_api_key:
            return "错误: 未找到有效的API密钥", "{}", ""
        
        # 构建基础数据
        data = {
            "web_app_id": int(web_app_id),
            "suppress_preview_output": True,
            "input_values": {}
        }
        
        # 处理图片输入（使用自定义字段映射）
        uploaded_images = []
        image_count = 0
        
        # 根据功能类型决定需要的图片数量
        type_image_count = {
            "单图修改": 1, "单图放大": 1, "单图重绘": 1,
            "双图融合": 2, "三图融合": 3, "四图融合": 4, "五图融合": 5
        }
        required_image_count = type_image_count.get(input_type, 1)
        
        # 收集图片数据和字段映射
        image_inputs = [
            (image_1, image_url_1, image_1_field),
            (image_2, image_url_2, image_2_field),
            (image_3, image_url_3, image_3_field),
            (image_4, image_url_4, image_4_field),
            (image_5, image_url_5, image_5_field)
        ]
        
        all_image_sources = []
        
        # 只检查需要的图片数量，确保每个位置只使用一种输入方式
        for i in range(required_image_count):
            image_file, image_url, field_mapping = image_inputs[i]
            
            print(f"检查位置{i+1}: file='{image_file}', url='{image_url}', field='{field_mapping}'")
            
            # 优先检查本地文件（第一优先级）
            has_valid_file = (
                image_file is not None and 
                str(image_file).strip() and 
                str(image_file) != 'None' and 
                str(image_file) != '' and
                str(image_file) != 'null'
            )
            
            # 只有在没有本地文件时才检查URL（第二优先级）
            has_valid_url = False
            if not has_valid_file and image_url and str(image_url).strip():
                url_str = str(image_url).strip()
                # 清理错误的URL值（Gradio bug）
                if url_str.startswith('/private/var/folders/') or url_str.startswith('/var/folders/') or url_str.startswith('/tmp/'):
                    print(f"警告: URL框 {i+1} 中发现文件路径，已忽略: {url_str}")
                    has_valid_url = False
                elif url_str.startswith('http://') or url_str.startswith('https://'):
                    has_valid_url = True
            
            # 根据优先级添加图片源（确保只使用一种方式）
            if has_valid_file:
                all_image_sources.append((str(image_file), 'file', i+1, field_mapping))
                print(f"✓ 位置{i+1}: 使用本地文件 -> {field_mapping}")
            elif has_valid_url:
                all_image_sources.append((url_str, 'url', i+1, field_mapping))
                print(f"✓ 位置{i+1}: 使用URL -> {field_mapping}")
            else:
                print(f"✗ 位置{i+1}: 无有效图片数据")
        
        print(f"需要{required_image_count}张图片，检测到{len(all_image_sources)}张")
        
        # 检查图片数量是否足够
        if len(all_image_sources) < required_image_count:
            error_msg = f"✗ {input_type}需要{required_image_count}张图片，但只检测到{len(all_image_sources)}张。\n请在激活的图片区域中上传足够的图片。"
            return error_msg, "{}", ""
        
        # 获取API密钥
        current_api_key = bizy_manager.get_current_api_key(api_key)
        if not current_api_key:
            return "错误: 未找到有效的API密钥", "{}", ""
        
        # 构建请求头
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {current_api_key}"
        }
        
        # 处理图片（使用自定义字段映射）
        for i in range(len(all_image_sources)):
            source_path, source_type, original_pos, field_mapping = all_image_sources[i]
            print(f"处理第{i+1}张图片: {source_path[:50]}... -> {field_mapping}")
            
            try:
                if source_type in ['file', 'url_as_file']:
                    base64_data, temp_path = bizy_manager.image_to_webp_base64(source_path)
                    data["input_values"][field_mapping] = base64_data
                    uploaded_images.append(f"本地文件: {source_path}")
                    image_count += 1
                    print(f"✓ 已处理本地图片 {i+1}: {temp_path} -> {field_mapping}")
                elif source_type == 'url':
                    data["input_values"][field_mapping] = source_path
                    uploaded_images.append(f"URL: {source_path}")
                    image_count += 1
                    print(f"✓ 已处理URL图片 {i+1}: {source_path} -> {field_mapping}")
            except Exception as e:
                print(f"✗ 第{i+1}张图片处理失败: {e}")
                return f"图片处理失败: {e}", "{}", ""
        
        # 添加文本提示词（使用自定义字段映射）
        if text_prompt and text_prompt.strip() and text_prompt_field and text_prompt_field.strip():
            data["input_values"][text_prompt_field.strip()] = text_prompt.strip()
            print(f"✓ 已添加文本提示词: {text_prompt.strip()} -> {text_prompt_field.strip()}")
        
        # 添加数值参数（使用自定义字段映射）
        if input_type == "单图放大" and float_field and float_field.strip():
            data["input_values"][float_field.strip()] = str(int(float_value))
            print(f"✓ 已添加放大倍数: {int(float_value)} -> {float_field.strip()}")
        
        # 添加整数参数（如果需要和有效）
        if (input_type in ["四图融合", "五图融合"] and  # 只有特定类型才使用
            int_field and int_field.strip() and 
            int_field.strip() != "custom:int.value" and  # 不是默认值
            int_field.strip() != ""):  # 不为空
            data["input_values"][int_field.strip()] = str(int(int_value))
            print(f"✓ 已添加整数参数: {int(int_value)} -> {int_field.strip()}")
        
        # 打印请求信息到终端（不包含base64数据）
        print(f"\n=== BizyAIR API请求 ===")
        print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"功能类型: {input_type}")
        print(f"Web App ID: {web_app_id}")
        print(f"已使用图片数量: {image_count}")
        if text_prompt:
            print(f"文本提示词: {text_prompt}")
        if input_type == "单图放大":
            print(f"放大倍数: {int(float_value)}")
        
        # 发送API请求
        print("正在发送API请求...")
        response = requests.post(bizy_manager.api_url, headers=headers, json=data, timeout=600)
        response.raise_for_status()
        
        result = response.json()
        print(f"API响应状态: {result.get('status', 'Unknown')}")
        
        # 提取结果信息
        request_id = result.get('request_id', '')
        outputs = result.get('outputs', [])
        
        if not outputs:
            return "API调用成功但未返回图片", json.dumps(result, ensure_ascii=False, indent=2), ""
        
        # 下载生成的图片
        downloaded_images = []
        for i, output in enumerate(outputs):
            try:
                object_url = output.get('object_url', '')
                if object_url:
                    # 生成文件名
                    filename = f"{request_id}_{i+1:02d}.png" if len(outputs) > 1 else f"{request_id}.png"
                    
                    # 下载图片
                    downloaded_path = bizy_manager.download_image(object_url, filename)
                    downloaded_images.append(downloaded_path)
                    print(f"已下载图片: {downloaded_path}")
                    
                    # 根据项目规范，保存同名txt文件记录图片信息
                    txt_filename = downloaded_path.replace('.png', '.txt')
                    try:
                        with open(txt_filename, 'w', encoding='utf-8') as txt_file:
                            txt_file.write(f"本地缓存路径: {downloaded_path}\n")
                            if text_prompt and text_prompt.strip():
                                txt_file.write(f"中文提示词: {text_prompt.strip()}\n")
                                # 简单的英文提示词（实际项目中可能需要翻译API）
                                txt_file.write(f"英文提示词: {text_prompt.strip()}\n")
                            txt_file.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                            txt_file.write(f"功能类型: {input_type}\n")
                            txt_file.write(f"API URL: {object_url}\n")
                        print(f"已保存图片信息文件: {txt_filename}")
                    except Exception as txt_e:
                        print(f"保存图片信息文件失败: {txt_e}")
                        
            except Exception as e:
                print(f"下载图片 {i+1} 失败: {e}")
        
        # 保存日志
        if downloaded_images:
            log_filename = request_id
            log_path = bizy_manager.save_log(log_filename, data, uploaded_images, request_id, outputs)
            print(f"已保存日志: {log_path}")
        
        # 准备返回信息
        success_msg = f"✅ 生成成功!\n"
        success_msg += f"任务ID: {request_id}\n"
        success_msg += f"生成图片数量: {len(outputs)}\n"
        for i, output in enumerate(outputs):
            success_msg += f"图片 {i+1} URL: {output.get('object_url', '')}\n"
        
        result_json = json.dumps(result, ensure_ascii=False, indent=2)
        
        # 返回第一张图片路径用于显示（确保路径存在）
        first_image = None
        if downloaded_images:
            first_path = downloaded_images[0]
            if os.path.exists(first_path):
                first_image = first_path
        
        return success_msg, result_json, first_image
        
    except requests.exceptions.RequestException as e:
        error_msg = f"API请求失败: {e}"
        print(error_msg)
        return error_msg, "{}", ""
    except Exception as e:
        error_msg = f"处理失败: {e}"
        print(error_msg)
        return error_msg, "{}", ""

def create_interface():
    """创建Gradio界面"""
    with gr.Blocks(title="BizyAIR API调用工具") as interface:
        # 美化的标题区域
        with gr.Row():
            gr.HTML("""
                <div style='text-align: center; margin-bottom: 30px; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; color: white;'>
                    <h1 style='font-size: 2.5rem; margin: 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);'>🎨 BizyAIR API调用工具</h1>
                    <p style='font-size: 1.2rem; margin: 10px 0 0 0; opacity: 0.9;'>支持多种图像生成和处理功能的专业工具</p>
                </div>
            """)
        
        with gr.Row():
            # 左侧列 - 配置和输入 (scale=4)
            with gr.Column(scale=4):
                # 基础配置 - API密钥和Web App ID同行
                with gr.Group():
                    gr.Markdown("### ⚙️ 基础配置")
                    with gr.Row():
                        api_key = gr.Textbox(
                            label="API密钥 (可选)",
                            placeholder="留空则使用环境变量 BIZYAIR_API_KEY",
                            type="password",
                            scale=2
                        )
                        web_app_id = gr.Number(
                            label="Web App ID（API远程应用的调用ID）",
                            value=36256,
                            precision=0,
                            # info="API远程应用的调用ID",
                            scale=1
                        )
                    
                    # 功能类型选择
                    input_type = gr.Radio(
                        choices=[
                            "单图修改", "单图放大", "单图重绘", 
                            "双图融合", "三图融合", "四图融合", "五图融合"
                        ],
                        label="功能类型",
                        value="五图融合"
                    )
                
                # 提交按钮
                submit_btn = gr.Button("🚀 生成图片", variant="primary", size="lg")
                
                # 输入字段
                with gr.Group():
                    gr.Markdown("### 📝 输入参数")
                    input_fields = create_input_fields()
                
            
            # 右侧列 - 结果显示 (scale=3)
            with gr.Column(scale=3):
                # 详细响应
                with gr.Group():
                    gr.Markdown("### 📋 API响应详情")
                    result_json = gr.JSON(label="完整响应")

                # 结果显示
                with gr.Group():
                    gr.Markdown("### 📊 生成结果")
                    generated_image = gr.Image(label="生成的图片", type="filepath")
                    result_status = gr.Textbox(label="生成状态", lines=6, interactive=False)
                
                # 使用说明移到这里
                with gr.Group():
                    gr.Markdown("### 📖 使用说明")
                    gr.HTML("""
                <div style='padding: 10px;'>
                    **功能说明：**<br />
                    - **单图修改** (ID: 36256)：上传1张图片 + 输入文字描述<br />
                    - **单图放大** (ID: 36258)：上传1张图片 + 设置放大倍数（1-4倍）<br />
                    - **单图重绘** (ID: 36259)：上传1张图片（无需其他参数）<br />
                    - **双图融合** (ID: 34887)：上传2张图片 + 输入融合描述<br />
                    - **三图融合** (ID: 36277)：上传3张图片 + 输入融合描述<br />
                    - **四图融合** (ID: 36278)：上传4张图片 + 输入融合描述<br />
                    - **五图融合** (ID: 36271)：上传5张图片 + 输入融合描述<br />
                    <br />
                    🔗 **图片输入方式：**<br />
                    - **本地上传优先**：如果同时有本地文件和URL，优先使用本地文件<br />
                    - **URL 输入**：只有在没有本地文件时才使用URL<br />
                    - **单一输入**：每个图片位置只使用一种输入方式<br />
                    <br />
                    <br />
                    💡 **提示**：选择不同功能类型时，Web App ID 会自动更新为对应的值。<br />
                </div>
            """)
        
        # 组件集合
        main_components = {
            'api_key': api_key,
            'web_app_id': web_app_id,
            'input_type': input_type
        }
        
        # 事件绑定
        
        # API密钥自动保存（当输入框内容变化时）
        def auto_save_api_key(api_key_input):
            if api_key_input and api_key_input.strip():
                return bizy_manager.save_api_key(api_key_input.strip())
            return ""
        
        api_key.change(
            fn=auto_save_api_key,
            inputs=[api_key],
            outputs=[],  # 不显示保存状态
            show_progress="hidden"
        )
        
        # 功能类型变化时更新输入字段可见性和web_app_id
        input_type.change(
            fn=update_input_visibility,
            inputs=[input_type],
            outputs=[
                web_app_id,
                # 文本提示词和字段映射
                input_fields['text_prompt'], input_fields['text_prompt_field'],
                # 图片和字段映射（每个图的3个组件）
                input_fields['image_1'], input_fields['image_url_1'], input_fields['image_1_field'],
                input_fields['image_2'], input_fields['image_url_2'], input_fields['image_2_field'],
                input_fields['image_3'], input_fields['image_url_3'], input_fields['image_3_field'],
                input_fields['image_4'], input_fields['image_url_4'], input_fields['image_4_field'],
                input_fields['image_5'], input_fields['image_url_5'], input_fields['image_5_field'],
                # 数值参数和字段映射
                input_fields['float_value'], input_fields['float_field'],
                input_fields['int_value'], input_fields['int_field']
            ]
        )
        
        # 提交处理
        submit_btn.click(
            fn=process_api_request,
            inputs=[
                api_key, web_app_id, input_type,
                # 文本提示词和字段映射
                input_fields['text_prompt'], input_fields['text_prompt_field'],
                # 图片、URL和字段映射
                input_fields['image_1'], input_fields['image_url_1'], input_fields['image_1_field'],
                input_fields['image_2'], input_fields['image_url_2'], input_fields['image_2_field'],
                input_fields['image_3'], input_fields['image_url_3'], input_fields['image_3_field'],
                input_fields['image_4'], input_fields['image_url_4'], input_fields['image_4_field'],
                input_fields['image_5'], input_fields['image_url_5'], input_fields['image_5_field'],
                # 数值参数和字段映射
                input_fields['float_value'], input_fields['float_field'],
                input_fields['int_value'], input_fields['int_field']
            ],
            outputs=[result_status, result_json, generated_image]
        )
    
    return interface

if __name__ == "__main__":
    # 启动界面
    interface = create_interface()
    interface.launch(
        server_name="0.0.0.0",
        server_port=7860,
        inbrowser=True,
        share=False,
        show_error=True,
        quiet=False
    )